﻿using Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Utility;

namespace Service
{
    public class winprop_service
    {
        private System.Timers.Timer timer = null;
        protected readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
        /// <summary>
        /// Service start
        /// </summary>
        public void Start()
        {
            //double interval = 1000;
            //this.timer = new System.Timers.Timer(interval);
            //this.timer.Elapsed += Timer_Elapsed;
            //this.timer.AutoReset = true;
            //this.timer.Enabled = true;
            //this.timer.Start();

            //this._logger.Info("winprop service start ......");

            Timer_Elapsed(null, null);
           
        }

        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //timer.Stop();

            //this.timer.AutoReset = false;
            //this.timer.Enabled = false;

            var config = Config.Init();

            int startFloot = config.StartFloor;
            int endFloot = config.EndFloor;

            _logger.Info("configuration initialized...");

            //读取工参
            System.Data.DataTable tabCell = Utility.ExcelUtil.ExcelToDataTable(config.CellFile, "站点信息", true);
            _logger.Info("读取工参");

            winprop.wrapper winpropwrapper = new winprop.wrapper();
            _logger.Info("类初始化");
            winpropwrapper.init("UTM", config.HorizontalOffset, config.VerticalOffset, config.CentralLongitude, config.CentralLatitude);
            _logger.Info("初始化winprop调用环境");

            
            string odaFilePath = winpropwrapper.BiuldODAFile(config.BuildSource, config.ResultFolder);
            winpropwrapper.load_building(odaFilePath);
            _logger.Info("生成oda文件");


            List<Res_Cell> cells = new List<Res_Cell>();
            winprop.Freq freq = new winprop.Freq();
            foreach (DataRow dr in tabCell.Rows)
            {
                
                Res_Cell cell = new Res_Cell();

                double mx = 0, my = 0;

                cell.CellName = dr["小区名称"].ToString().Replace('\\', '_');
                cell.HorizonAngleToEast = (int)Convert.ToDouble(dr["扇区方位角"]);
                cell.VerticalAngleToHorizontal = (int)Convert.ToDouble(dr["总下倾角"]);
                if (cell.VerticalAngleToHorizontal > 0) {
                    cell.VerticalAngleToHorizontal = cell.VerticalAngleToHorizontal - 6;
                }
                cell.Longitude = Convert.ToDouble(dr["小区经度"]);
                cell.Latitude = Convert.ToDouble(dr["小区纬度"]);
                cell.ObjectID = Convert.ToInt32(dr["ObjectId"]);
                cell.AntHeight = Convert.ToDouble(dr["天线挂高[m]"]);
                cell.RSTxPower = Convert.ToDouble(dr["CRS信道发射功率[dBm]"]);
                cell.Frequency = freq.GetFreqByCenterChannelNumber((dr["中心频点"]).ToString());

                MecatorUtil.loc_to_mercator(cell.Longitude, cell.Latitude, ref mx, ref my);

                cell.CellLongitude = mx;
                cell.CellLatitude = my;

                cells.Add(cell);
                
            }

            tabCell.Dispose();
            tabCell = null;
            
            /*分配多线程*/
            int parallelThreadCount = 16;
            int threadContentCount = cells.Count() / parallelThreadCount;
            if (threadContentCount == 0)
            {
                threadContentCount = cells.Count;
            }

            if (cells.Count % parallelThreadCount > 0)
            {
                threadContentCount++;
            }
            List<List<Res_Cell>> cellThreadList = new List<List<Res_Cell>>();
            for (int i = 0; i < parallelThreadCount; i++)
            {
                cellThreadList.Add(cells.Skip(i * threadContentCount).Take(threadContentCount).ToList());
            }

            for (int i = startFloot; i <= endFloot; i++)
            {
                _logger.Info("第" + i + "层开始输出");
                Parallel.ForEach(cellThreadList, new ParallelOptions() { MaxDegreeOfParallelism = parallelThreadCount }, (List<Res_Cell> cellThread) =>
                {
                    foreach (var cell in cellThread)
                    {
                        string winpropOutFolder = Path.Combine(config.ResultFolder, config.GridLength.ToString());
                        string winpropOutFile = Path.Combine(winpropOutFolder, i.ToString(), string.Format("{0}_OutdoorOutput.txt", cell.CellName));

                        if (File.Exists(winpropOutFile) == false)
                        {
                            if (!Directory.Exists(winpropOutFolder))
                            {
                                Directory.CreateDirectory(winpropOutFolder);
                            }

                            if (!Directory.Exists(winpropOutFolder + "\\" + i))
                            {
                                Directory.CreateDirectory(winpropOutFolder + "\\" + i);
                            }
                        }
                        else
                        {
                            continue;
                        }

                        string winpropOutFloorFolder = Path.Combine(winpropOutFolder, i.ToString());
                        try
                        {
                            winpropwrapper.call_winprop(odaFilePath, winpropOutFile, config.GridLength, 500, i, cell);
                        }
                        catch
                        {
                            Thread.Sleep(1000);
                            try
                            {
                                winpropwrapper.call_winprop(odaFilePath, winpropOutFile, config.GridLength, 500, i, cell);
                            }
                            catch {
                                Thread.Sleep(2000);
                                winpropwrapper.call_winprop(odaFilePath, winpropOutFile, config.GridLength, 500, i, cell);
                            }
                        }
                    }
                });

                _logger.Info("第" + i + "层winprop输出完成, 小区总数：" + cells.Count);
            }
            winpropwrapper.release_building();
            _logger.Info(startFloot + "-" + endFloot + "层winprop输出完成");

            _logger.Info(startFloot + "-" + endFloot + "层开始合成");
            Codes.WinProp_CombineFile combineFile = new Codes.WinProp_CombineFile();
            combineFile.Execute(config.SliceLength, 1, 2000000, new SyntheticPar()
            {
                CellPath = config.CellFile,
                City = config.City,
                GridLength = config.GridLength,
                ResultFolder = config.ResultFolder
            });
            _logger.Info(startFloot + "-" + endFloot + "层合成完毕");

            Codes.WinProp_UploadFtp upload = new Codes.WinProp_UploadFtp();
            upload.Execute(Path.Combine(config.ResultFolder, "combine"), config.City);
            _logger.Info(startFloot + "-" + endFloot + "上传完毕");

        }
        public void Stop()
        {
            this.timer.Stop();
            this.timer.AutoReset = false;
            this.timer.Enabled = false;

            this._logger.Info("winprop service stop ....");
        }
    }
}
